﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using VNet.VisiSuite.Common;
using VNet.VisiSuite.Common.Resource;
using VNet.VisiSuite.Controls;
using VNet.VisiSuite.Service.Contact.Enum;
using VNet.VisiSuite.Service.Contact.Message.Base;
using VNet.VisiSuite.Service.Contact.Message.Item;
using VNet.VisiSuite.VisiAdmin.Common;
using VNet.VisiSuite.VisiAdmin.Common.Helpers;
using VNet.VisiSuite.VisiAdmin.Models;
using VNet.VisiSuite.VisiAdmin.Providers;
using VNet.VisiSuite.VisiAdmin.Views;

namespace VNet.VisiSuite.VisiAdmin.ViewModels
{
    public class UserViewModel : BaseViewModel
    {
        #region Fields
        private UserModel _cloneSelectedUser;
        private UserModel _selectedUser;
        private ObservableCollection<UserModel> _users;
        private UserModel _pendingUser;

        #endregion

        public UserViewModel()
        {
            PageTitle = TitleString.UserViewAdminTitle;

            TopRightButtonIcons = new ObservableCollection<VNetMenuItem> { new VNetMenuItem(null, "Add new user", CommonConstants.VNetIcon.AppbarListAdd, VNetMenuItemType.WhiteBackgroundTheme, OnAddNewUser), };
            TopLeftButtonIcons = new ObservableCollection<VNetMenuItem> { new VNetMenuItem(null, "Return to previous screen", CommonConstants.VNetIcon.AppbarArrowLeft, VNetMenuItemType.WhiteBackgroundTheme, OnExit), };

            SaveCommand = new RelayCommand(DoUpdateUser);
            CancelCommand = new RelayCommand(DoCancel);
            DeleteCommand = new RelayCommand(DoDeleteUser);


            Users = new ObservableCollection<UserModel>();
        }

        private void DoDeleteUser(object obj)
        {
            ErrorMessage = null;
            if (MessageBox.Show(string.Format(FormatString.DeleteItemFormat, "user"), TitleString.ConfirmDeleteTitle, MessageBoxButton.YesNo) == MessageBoxResult.No)
                return;

            IsBusy = true;
            DoAsync(UserProvider.DeleteUser, DeleteUserCompleted, CloneSelectedUser.UserLoginId);
        }

        private void DeleteUserCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as DeleteDataResponse;

            if (response == null || !response.Success)
            {
                IsBusy = false;
                if (response != null)
                {
                    CloneSelectedUser.ErrorMessage = response.Error.Description;
                }
                _pendingUser = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                IsBusy = false;
                NavigateBack();
                return;
            }

            CloneSelectedUser = null;
            SelectedUser = null;

            var item = Users.FirstOrDefault(t => t.UserLoginId == response.DataId);
            if (item != null)
                Users.Remove(item);
            IsBusy = false;
        }

        #region Properties

        public ObservableCollection<UserModel> Users
        {
            get { return _users; }
            set
            {
                _users = value;
                OnPropertyChanged("Users");
            }
        }

        public UserModel SelectedUser
        {
            get { return _selectedUser; }
            set
            {
                if (value != null && IsUserPendingChange(value))
                    return;

                //Must set to null to unhighlight the active item on UI
                _selectedUser = null;
                OnPropertyChanged("SelectedUser");

                //Continue the business logic
                _pendingUser = null;
                _selectedUser = value;
                if (_selectedUser != null)
                {
                    CloneSelectedUser = SmartReflection.CloneModel(_selectedUser);
                    CloneSelectedUser.ShouldValidate = true;
                }
                OnPropertyChanged("SelectedUser");
            }
        }

        public UserModel CloneSelectedUser
        {
            get { return _cloneSelectedUser; }
            set
            {
                _cloneSelectedUser = value;
                OnPropertyChanged("CloneSelectedUser");
            }
        }

        #endregion

        #region Methods

        private void OnExit()
        {
            IsClosing = true;
            if (IsUserPendingChange(null))
                return;

            NavigateBack();
        }

        private void DoUpdateUser(object obj)
        {
            if (!CloneSelectedUser.IsValid())
                return;

            var permission = UserPermission.None;
            if (CloneSelectedUser.IsEditPart)
                permission |= UserPermission.EditParts;
            if (CloneSelectedUser.IsEditUsers)
                permission |= UserPermission.EditUsers;

            var userItem = new UserLoginItem
            {
                Login = CloneSelectedUser.Login,
                Email = CloneSelectedUser.Email,
                Enabled = CloneSelectedUser.IsEnabled,
                FirstName = CloneSelectedUser.FirstName,
                LastName = CloneSelectedUser.LastName,
                Password = CloneSelectedUser.Password,
                Permission = permission,
                UserLoginId = CloneSelectedUser.UserLoginId,
            };

            IsBusy = true;
            if (CloneSelectedUser.IsAddNew)
                DoAsync(UserProvider.InsertUser, InsertUserCompleted, userItem);
            else
                DoAsync(UserProvider.UpdateUser, UpdateUserCompleted, userItem);
        }

        private void DoCancel(object obj)
        {
            CloneSelectedUser = CloneSelectedUser.IsAddNew ? null : SmartReflection.CloneModel(SelectedUser);
        }

        private void OnAddNewUser()
        {
            //Init new data for add new function
            SelectedUser = new UserModel { IsAddNew = true };
        }

        private void GetUserCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as GetDataResponse<IList<UserLoginItem>>;
            if (response != null && response.Data != null)
            {
                Users = new ObservableCollection<UserModel>();
                foreach (UserLoginItem user in response.Data.OrderBy(item => item.Login))
                {
                    Users.Add(ConvertItemToModel(user));
                }
            }
            IsBusy = false;
        }

        private void UpdateUserCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<UserLoginItem>;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    CloneSelectedUser.ErrorMessage = response.Error.Description;

                CloneSelectedUser.IsCancelEnable = false;
                _pendingUser = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                NavigateBack();
                return;
            }

            _selectedUser.FirstName = response.Data.FirstName;
            _selectedUser.LastName = response.Data.LastName;
            _selectedUser.Email = response.Data.Email;
            _selectedUser.Login = response.Data.Login;
            _selectedUser.IsEnabled = response.Data.Enabled;
            _selectedUser.UserLoginId = response.Data.UserLoginId;
            _selectedUser.LastUpdatedByUser = response.Data.LastUpdatedByUser;
            _selectedUser.LastUpdatedDate = response.Data.LastUpdatedDate.ToString(FormatString.DateTimeFormat);
            if (response.Data.Permission.Equals(UserPermission.EditParts))
                _selectedUser.IsEditPart = true;
            if (response.Data.Permission.Equals(UserPermission.EditUsers))
                _selectedUser.IsEditUsers = true;
            if (response.Data.Permission.Equals(UserPermission.EditUsers | UserPermission.EditParts))
            {
                _selectedUser.IsEditUsers = true;
                _selectedUser.IsEditPart = true;
            }
            if (response.Data.Permission.Equals(UserPermission.None))
            {
                _selectedUser.IsEditUsers = false;
                _selectedUser.IsEditPart = false;
            }

            _selectedUser.IsChange = false;
            _selectedUser.ErrorMessage = null;
            _selectedUser.IsCancelEnable = false;
            _selectedUser.Password = null;
            _selectedUser.PasswordConfirmed = null;
            CloneSelectedUser = SmartReflection.CloneModel(SelectedUser);
            if (_pendingUser != null)
            {
                SelectedUser = _pendingUser;
                _pendingUser = null;
            }
        }

        private void InsertUserCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<UserLoginItem>;
            IsBusy = false;
            if (response == null || !response.Success)
            {
                CloneSelectedUser.ErrorMessage = response.Error.Description;
                _pendingUser = null;
                IsClosing = false;
                return;
            }
            if (IsClosing)
            {
                NavigateBack();
                return;
            }

            var newModel = ConvertItemToModel(response.Data);

            Users.Add(newModel);
            CloneSelectedUser = null;
            SelectedUser = _pendingUser ?? newModel;
            _pendingUser = null;
        }

        private void NavigateBack()
        {
            NavigationManager.NavigateTo(new PlantView(), null);
        }

        private UserModel ConvertItemToModel(UserLoginItem item)
        {
            if (item == null)
                return null;

            var model = new UserModel
            {
                UserLoginId = item.UserLoginId,
                FirstName = item.FirstName,
                LastName = item.LastName,
                Email = item.Email,
                Login = item.Login,
                IsEnabled = item.Enabled,
                CreatedDate = item.CreatedDate.ToString(FormatString.DateTimeFormat),
                LastUpdatedDate = item.LastUpdatedDate.ToString(FormatString.DateTimeFormat),
                CreatedByUser = item.CreatedByUser,
                LastUpdatedByUser = item.LastUpdatedByUser,
            };
            if (item.Permission.Equals(UserPermission.EditParts))
                model.IsEditPart = true;
            if (item.Permission.Equals(UserPermission.EditUsers))
                model.IsEditUsers = true;
            if (item.Permission.Equals(UserPermission.EditUsers | UserPermission.EditParts))
            {
                model.IsEditUsers = true;
                model.IsEditPart = true;
            }
            return model;
        }

        public bool IsUserPendingChange(UserModel value)
        {
            if (_cloneSelectedUser != null && _cloneSelectedUser.HasChange())
            {
                switch (ConfirmDialog.Show())
                {
                    case SaveChangesDialogResult.Discard:
                        return false;
                    case SaveChangesDialogResult.Save:
                        _pendingUser = value;
                        DoUpdateUser(null);
                        return true;
                    case SaveChangesDialogResult.Resume:
                        IsClosing = false;
                        _pendingUser = null;
                        return true;
                }
            }
            return false;
        }

        #endregion

        #region Navigation Framwork
        public override void OnNavigate(object obj)
        {
            IsBusy = true;
            DoAsync(UserProvider.GetUsers, GetUserCompleted);
        }

        public override void OnLeave()
        {
        }
        #endregion
    }
}
